package engine

type QueuedScheduler struct {
	Scheduler
	Fetcher
	WorkerCount int
	ItemSaver chan interface{}
}
type Scheduler interface {
	ReadyNotifier
	WorkerChan() chan Request
	Submit(Request)
	Run()
}
type ReadyNotifier interface {
	WorkerReady(chan Request)
	WorkerStatus(*Request,error)
}
type Fetcher interface {
	Worker(*Request) (ParserResult, error)
}
func (e QueuedScheduler) Run(seed ... Request) {
	e.Scheduler.Run()
	out := make(chan ParserResult)
	for i := 0; i < e.WorkerCount; i++ {
		createWorker(e.WorkerChan(), out, e.Scheduler,e.Fetcher)
	}
	for _, r := range seed {
		e.Scheduler.Submit(r)
	}
	for {
		request := <-out
		for _, request := range request.Requests {
			e.Submit(request)
		}
		for _, item := range request.Items {
			go func(i interface{}) {
				e.ItemSaver<-i
				}(item)
		}
	}
}
func createWorker(in chan Request, out chan ParserResult, e ReadyNotifier,f Fetcher) {
	go func() {
		for {
			e.WorkerReady(in)
			request := <-in
			result, err := f.Worker(&request)
			if err != nil {
				e.WorkerStatus(&request,err)
				continue
			}
			out <- result
		}
	}()
}
